package com.sec.android.app.myfiles.module.download;

import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteFullException;
import android.net.Uri;
import android.support.v4.content.LocalBroadcastManager;

import com.sec.android.app.myfiles.info.AppConstants;
import com.sec.android.app.myfiles.info.MediaFile;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.module.abstraction.AbsProviderImp;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.module.abstraction.FileRecord.StorageType;
import com.sec.android.app.myfiles.module.download.providerapps.AbsSupportAppProviderImp;
import com.sec.android.app.myfiles.module.download.providerapps.BluetoothProviderImp;
import com.sec.android.app.myfiles.module.download.providerapps.BrowserProviderImp;
import com.sec.android.app.myfiles.module.download.providerapps.SimpleShareProviderImp;
import com.sec.android.app.myfiles.provider.DbTableInfo.COLUMN_ID;
import com.sec.android.app.myfiles.util.SemFwWrapper;
import com.sec.android.app.myfiles.util.chain.ChainBuilder;

import java.io.File;

/**
 * @author jae.bae
 * @TODO should consider for MMS, WIFI direct (these apps insert directly)
 */
public class DownloadProviderImp extends AbsProviderImp {
    private static final int DB_VER_COL_ADDED_FROM_S_BROWSER = 307;
    private static boolean sIsUpdated;
    protected AbsSupportAppProviderImp mSupportApps;
    private BrowserProviderImp mBrowserProviderImp = null;

    public DownloadProviderImp(Context context) {
        super(context);
    }

    @Override
    protected void onSetDB() {
        Log.d(this, "onSetDB() : sIsUpdated = " + sIsUpdated);
        mSupportApps = getSupportAppProviderImp();
        if (sIsUpdated) {
            Log.d(this, "onSetDB() : sIsUpdated is true so refresh DB");
            if (mBrowserProviderImp != null) {
                mBrowserProviderImp.refreshForce(Uri.parse(mDbTableInfo.getUri()));
            }
            sIsUpdated = false;
        }
    }

    protected AbsSupportAppProviderImp getSupportAppProviderImp() {
        Log.d(this, "getSupportAppProviderImp()");
        mBrowserProviderImp = new BrowserProviderImp(mContext, this, mDB);
        ChainBuilder<AbsSupportAppProviderImp> builder = new ChainBuilder<>().
                append(mBrowserProviderImp).
                append(new SimpleShareProviderImp(mContext, this, mDB)).
                append(new BluetoothProviderImp(mContext, this, mDB));
        return builder.getInstance();
    }

    @Override
    protected StorageType getStorage() {
        return StorageType.Downloads;
    }

    @Override
    protected boolean needRefresh(Uri uri, FileRecord curRecord) {
        return true;
    }

    @Override
    protected void _refreshDB(Uri uri, FileRecord curRecord) {
        if (mSupportApps != null && uri != null) {
            Log.d(this, "_refreshDB()");
            mSupportApps.refresh(uri);
        }
    }

    @Override
    protected Cursor _query(Uri uri, String[] projectionIn, String selection, String[] selectionArgs, String sortOrder) {
        final String _selection = " ( " + mDbTableInfo.getColumnName(COLUMN_ID.DOWNLOADED_ITEM_VISIBILITY) + " = 1 ) ";
        if (selection == null || selection.isEmpty()) {
            selection = _selection;
        } else {
            selection = selection + " AND " + _selection;
        }

        return super._query(uri, projectionIn, selection, selectionArgs, sortOrder);
    }

    /**
     * download provider delete is not real db delete, but update DOWNLOADED_ITEM_VISIBILITY column to false.
     */
    @Override
    protected int _delete(String selection, String[] selectionArgs) {
        ContentValues values = new ContentValues();

        final String colVisibility = mDbTableInfo.getColumnName(COLUMN_ID.DOWNLOADED_ITEM_VISIBILITY);
        values.put(colVisibility, false);

        return super._update(values, selection, selectionArgs);
    }

    /**
     * Downloaded files via MMS, WiFi direct only have three column values : _data, _description, _download_by so it needs to fill in other
     * column values.
     */
    @Override
    protected Uri _insert(Uri uri, ContentValues values) {
        boolean fromOutOfMyFiles = values != null &&
                values.getAsInteger(mDbTableInfo.getColumnName(COLUMN_ID.DOWNLOAD_BY)) != null;
        if (fromOutOfMyFiles) {
            String fullPath = values.getAsString(mDbTableInfo.getColumnName(COLUMN_ID.PATH));
            if (fullPath != null) {
                File file = SemFwWrapper.file(fullPath);
                values.put(mDbTableInfo.getColumnName(COLUMN_ID.DOWNLOAD_ID), 1);
                values.put(mDbTableInfo.getColumnName(COLUMN_ID.NAME), file.getName());
                values.put(mDbTableInfo.getColumnName(COLUMN_ID.FILE_TYPE), MediaFile.getFileType(fullPath));
                values.put(mDbTableInfo.getColumnName(COLUMN_ID.SIZE), file.length());
                values.put(mDbTableInfo.getColumnName(COLUMN_ID.DATE), file.lastModified());
                values.put(mDbTableInfo.getColumnName(COLUMN_ID.PATH), FileRecord.getPath(fullPath));
                values.put(mDbTableInfo.getColumnName(COLUMN_ID.EXT), FileRecord.getExt(fullPath));
                values.put(mDbTableInfo.getColumnName(COLUMN_ID.MIME_TYPE), MediaFile.getMimeType(fullPath));
                values.put(mDbTableInfo.getColumnName(COLUMN_ID.SOURCE), "");
                values.put(mDbTableInfo.getColumnName(COLUMN_ID.STATUS), 8);
                values.put(mDbTableInfo.getColumnName(COLUMN_ID.DOWNLOADED_ITEM_VISIBILITY), 1);
            }
        }
        Uri result = super._insert(uri, values);
        if (result != null && fromOutOfMyFiles) {
            Intent intent = new Intent(AppConstants.MYFILES_ACTION_DOWNLOAD_HISTORY_INSERTED);
            LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
        }
        return result;
    }

    @Override
    protected void updateTable(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.d(this, "oldVersion " + oldVersion + " newVersion " + newVersion);
        if (oldVersion > MIN_MYFILE_2016_DB_VERSION) {
            Log.d(this, "alter table");
            try {
                db.beginTransaction();
                if (oldVersion < DB_VER_COL_ADDED_FROM_S_BROWSER) {
                    db.execSQL("ALTER TABLE " + mDbTableInfo.getTableName() +
                            " ADD COLUMN " + mDbTableInfo.getColumnName(COLUMN_ID.FROM_S_BROWSER) + " integer");
                }
                db.setTransactionSuccessful();
            } catch (SQLiteFullException e) {
                Log.e(this, "SQLiteFullException:" + e.toString());
            } catch (IllegalStateException e) {
                Log.e(this, e.getMessage());
            } finally {
                Log.d(this, "updateTable finally");
                sIsUpdated = true;
                db.endTransaction();
            }
        } else {
            super.updateTable(db, oldVersion, newVersion);
        }
    }
}
